using System.Collections.Generic;
using CoreVirtuoso.Descriptions;
using Infrastructure.Events.Interfaces;
using NGenerics.DataStructures;
using VirtuosoDal.Repositories.RdfRepositories.Events;
using VirtuosoDal.Repositories.RdfRepositories.Interfaces.Events;

namespace Infrastructure.Events
{
   public class EventsOntologyClassesTreeBuilder : IEventsOntologyClassesTreeBuilder
   {
      private readonly IEventsOntologyRepository _eventsOntologyRepository;

      public EventsOntologyClassesTreeBuilder(IEventsOntologyRepository eventsOntologyRepository)
      {
         _eventsOntologyRepository = eventsOntologyRepository;
      }

      public GeneralTree<EntityDescription> GetClassesTree(string rootClassUri, string language)
      {
         // We don't use rootClass, so we don't need it's label
         var rootClassDescription = new EntityDescription(rootClassUri, null);
         var classesTree = new GeneralTree<EntityDescription>(rootClassDescription);

         GetClassesTreeInternal(classesTree, language);

         return classesTree;
      }

      /// <summary>
      /// This method is called recursively
      /// </summary>
      private void GetClassesTreeInternal(GeneralTree<EntityDescription> parentNode,
         string language)
      {
         List<EntityDescription> childrenClasses =
            _eventsOntologyRepository.GetChildClasses(parentNode.Data.Uri.OriginalString, language);

         EntityDescription otherCategoryEntityDescription = childrenClasses.Find(ed => ed.Uri.Fragment.Substring(1).StartsWith("Other"));
         if (otherCategoryEntityDescription != null)
         {
            // Move otherCategoryEntityDescriptiont to the end of list
            childrenClasses.Remove(otherCategoryEntityDescription);
            childrenClasses.Add(otherCategoryEntityDescription);
         }

         foreach (EntityDescription childEntityDescription in childrenClasses)
         {
            GeneralTree<EntityDescription> childNode = new GeneralTree<EntityDescription>(childEntityDescription);
            parentNode.Add(childNode);
            GetClassesTreeInternal(childNode, language);
         }
      }
   }
}